ログファイルの共有に困っていませんか? 署名付き URL で S3 にアップロードしよう

ログファイルの共有に困っていませんか? 署名付き URL で S3 にアップロードしよう

Clock Icon2024.11.18

こんにちは。テクニカルサポートチームのShiinaです。

はじめに

運用中のシステムで障害が発生した際、技術的な支援を求めサポートへお問い合わせする機会がありますよね。
スムーズな解決のため、ログファイルなどの情報提供をお願いされた場合にファイル容量やセキュリティ的な制約によりファイルの共有に困ったことはありませんか?
ファイルの受け渡しの一時的なストレージとして S3 の利用が考えられますが、AWS CLI や SDK がインストールされていない環境や S3 バケットに対するアクセス権限が制限されている場合などにはアップロードが困難です。
S3 の署名付き URL を利用すると、一時的なアクセス権が提供され、セキュアにファイルをアップロードできます。
今回、署名付き URL を使ってログファイルを S3 バケットにアップロードしてみました。
アップロードは curl や Invoke-WebRequest コマンドを利用して行えます。

前提

  • S3 バケットが作成済みであること
  • インターネット、プロキシサーバ、VPC エンドポイント等を利用して S3 へ通信できること
  • Linux の場合、curl コマンドが利用できること
  • Windows の場合、Invoke-WebRequest コマンドが利用できること

やってみた

アップロードが行える署名付き URL の発行には SDK を利用する必要があります。
今回は EC2 インスタンスで Boto3 を利用して発行してみました。

署名付き URL の発行用 IAM ポリシー

アップロードが行える署名付き URL の発行には s3:PutObject の許可ポリシーが必要です。
署名付き URL の発行に利用する EC2 インスタンスロールにポリシーを付与します。

Resource の arn はアップロードする S3 バケットに修正してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::xxxxxxxxxx/*"
            ]
        }
    ]
}

ec2-ssm-s3-role-IAM-Global-11-14-2024_06_19_PM

署名付き URL 発行

boto3 を利用して署名付き URL を発行します。
今回は下記コードを利用して発行してみました。

generate_presigned_url.py
import sys
import boto3

def get_signed_url(bucket_name, file_name):

    # AWS クライアントを東京リージョンで作成
    s3 = boto3.client('s3', region_name='ap-northeast-1')

    # 署名付きURLの有効期限を3600秒(1時間)
    expiration_seconds = 3600

    # 署名付きURLを生成
    signed_url = s3.generate_presigned_url(
        ClientMethod='put_object',
        Params={
            'Bucket': bucket_name,
            'Key': file_name
        },
        ExpiresIn=expiration_seconds
    )

    return signed_url

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: python script.py <bucket_name> <file_name>")
        sys.exit(1)

    bucket_name = sys.argv[1]
    file_name = sys.argv[2]
    signed_url = get_signed_url(bucket_name, file_name)
    print(signed_url)

バケット名、アップロードしたいファイル名を引数に指定してコードを実行すると署名付き URL が発行されます。
バケット名 bucketname に対して Linux_log.zip というファイルをアップロードする実行例は次の通りです。

python3 generate_presigned_url.py bucketname Linux_log.zip

https://s3.ap-northeast-1.amazonaws.com/バケット名/Linux_log.zip?AWSAccessKey〜〜

ファイルアップロード(Linux)

署名付き URL に対して curl コマンドでアップロードが行えます。
Linux_log.zip ファイルをアップロードする実行例は次の通りです。

curl -X PUT -i -T "Linux_log.zip" "署名付きURL"

200 OK の応答があればアップロード成功です。

HTTP/1.1 200 OK
x-amz-id-2: xxxxxxxxxxxxxxxx
x-amz-request-id: xxxxxxxx
Date: Tue, 12 Nov 2024 08:57:30 GMT
x-amz-server-side-encryption: AES256
ETag: "xxxxxxxx"
Content-Length: 0
Server: AmazonS3

S3 バケットを見てみます。
オブジェクト一覧にファイル名が表示されたことが確認できます。

linuxs3

ファイルアップロード(Windows)

署名付き URL に対して Invoke-WebRequest コマンドでアップロードが行えます。
Windows_log.zip ファイルをアップロードする実行例は次の通りです。

Invoke-WebRequest -UseBasicParsing -Method Put -InFile "Windows_log.zip" -Uri "署名付きURL"

200 OK の応答があればアップロード成功です。

StatusCode        : 200
StatusDescription : OK
Content           : {}
RawContent        : HTTP/1.1 200 OK
                    x-amz-id-2: xxxxxxxxxxxxxxxx
                    x-amz-request-id: xxxxxxxxxxxxxxxx
                    x-amz-server-side-encryption: AES256
                    Content-Length: 0
                    ...
Headers           : {[x-amz-id-2, xxxxxxxxxxxxxxxx], [x-amz-request-id, xxxxxxxxxxxxxxxx], [x-amz-server-side-encryption, AES256], [Conte
                    nt-Length, 0]...}
RawContentLength  : 0

S3 バケットを見てみます。
こちらもオブジェクト一覧にファイル名が表示されたことが確認できます。

wins3

まとめ

直接 S3 へアップロードできない環境においても署名付き URL を利用することでセキュアにファイルの受け渡しができます。
EC2 インスタンスに限らず、オンプレミスやコンテナ環境、ローカル PC におても必要なログファイルを S3 にアップロードすることができます。
本記事がログファイル共有の悩みの解決につながれば幸いです。

参考

https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_PresignedUrl_section.html

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.